package 晚间作业0323;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Doc15_课后作业 {
    public static void main(String[] args) {

    }

    /**
     * 1. 创建一个Map集合，存入5个学生信息，使用学号和学生基本信息进行对应，
     *   学生基本信息包括姓名，年龄，专业，遍历输出。
     */
    public static class Q01 {
        public static void main(String[] args) {
            Map<String, Student> infos = new HashMap<>();
            infos.put("2014011647", new Student("xiaoming", 20, "软件工程"));
            infos.put("2014011648", new Student("xiaohong", 22, "软件工程"));
            infos.put("2014011649", new Student("zhangsan", 24, "软件工程"));
            infos.forEach((sn, item) -> System.out.println(item));
        }

        private static class Student {
            private String name;
            private int age;
            private String major;

            public Student(String name, int age, String major) {
                this.name = name;
                this.age = age;
                this.major = major;
            }

            @Override
            public String toString() {
                return "{" +
                        "name='" + name + '\'' +
                        ", age=" + age +
                        ", major='" + major + '\'' +
                        '}';
            }
        }
    }

    /**
     * 2. 有两个班级，一班和二班，每个班级有若干学生，包含学号和姓名信息，要求能够完全保存班级和学生信息，遍历输出。
     */
    public static class Q02 {
        public static void main(String[] args) {
            Map<String, List<Student>> classMap = new HashMap<>(2);
            classMap.put("一班", Arrays.asList(
                    new Student("小明", "0101"),
                    new Student("小红", "0102"),
                    new Student("小绿", "0103")
            ));
            classMap.put("二班", Arrays.asList(
                    new Student("大明", "0201"),
                    new Student("大红", "0202"),
                    new Student("大绿", "0203")
            ));
            classMap.forEach((s, students) -> System.out.println(s + "==>" + students));
        }

        private static class Student {
            private String name;
            private String sn;
            public Student(String name, String sn) {
                this.name = name;
                this.sn = sn;
            }

            @Override
            public String toString() {
                return "{" +
                        "name: '" + name + '\'' +
                        ", sn: '" + sn + '\'' +
                        '}';
            }
        }
    }

    /**
     * 3. 有长度为5的字符串数组，数组中的每个元素均为一个标准英文句子，要求借助Map集合统计每个单词出现的次数。
     */
    public static class Q03 {
        public static void main(String[] args) {
            String[] data = {"hello world", "at qianfeng", "how are you", "hello qianfeng"};
            Map<String, Integer> result = new TreeMap<>();
            Arrays.stream(data)
                    .flatMap((Function<String, Stream<String>>) s -> Arrays.stream(s.split("\\s+")))
                    .forEach(s -> {
                        if (!result.containsKey(s)) {
                            result.put(s, 1);
                        } else {
                            result.put(s, result.get(s) + 1);
                        }
                    });
            System.out.println(result);
        }
    }

    /**
     * 编写一个自动发牌程序，模拟三人斗地主的摸牌场景。首先要给出提示，谁首先开始摸牌，并且摸牌要和现实摸 牌一样，
     * 三人循环摸牌，最后还要剩余三张底牌，同时给出地主牌，摸到地主牌的玩家拥有三张底牌。三张底牌三 人都可以看到。
     * 当三张底牌派发给地主后提示玩家摸牌结束
     */
    @SuppressWarnings("unchecked")
    public static class Q06 {
        public static void main(String[] args) {
            // 扑克牌存放set
            Set<String> pokers = new LinkedHashSet<>();
            // 玩家手牌
            List<String> player1 = new ArrayList<>(17);
            List<String> player2 = new ArrayList<>(17);
            List<String> player3 = new ArrayList<>(17);
            // 洗牌
            shuffle(pokers);
            System.out.println(pokers);
            // 获取3张底牌和1张地主牌
            String[] remainAndSelectLord = getRemainAndSelectLord(pokers);
            int beginIdx = new Random().nextInt(3);
            System.out.println("玩家" + (beginIdx + 1) + "先摸牌");
            System.out.println("派牌开始！");
            deal(pokers, beginIdx, player1, player2, player3);
            System.out.println("派牌结束！");
            System.out.println("底牌是: " + Arrays.toString(new String[] {remainAndSelectLord[0], remainAndSelectLord[1], remainAndSelectLord[2]}));
            System.out.println("地主牌是: " + remainAndSelectLord[3]);
            // 寻找地主，给底牌
            int lordPlayer = findLordAndSendRemainPokers(remainAndSelectLord, player1, player2, player3);
            System.out.println("地主是玩家" + lordPlayer);
            System.out.println("玩家1的手牌是：" + player1);
            System.out.println("玩家2的手牌是：" + player2);
            System.out.println("玩家3的手牌是：" + player3);
        }

        /**
         * 根据扑克索引获取扑克面值
         */
        public static String getPokerByIdx(int cardIndex) {
            if (cardIndex == 52) {
                return "大王";
            } else if (cardIndex == 53) {
                return "小王";
            }
            char[] marks = {'♥', '♠', '♣', '♦'};
            String[] values = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
            return marks[cardIndex % 4] + values[cardIndex % 13];
        }

        /**
         * 找到地主，并给他底牌
         */
        public static int findLordAndSendRemainPokers(String[] remainAndSelectLord, List<String>... players) {
            for (int i = 0; i < players.length; i++) {
                List<String> player = players[i];
                if (player.contains(remainAndSelectLord[3])) {
                    // 找到地主，给底牌
                    player.addAll(Arrays.asList(remainAndSelectLord[0], remainAndSelectLord[1], remainAndSelectLord[2]));
                    return i + 1;
                }
            }
            return -1;
        }

        /**
         * 洗牌
         */
        public static void shuffle(Set<String> pokers) {
            Random random = new Random();
            int[] idx = new int[54];
            for (int i = 0; i < 54; i++) { idx[i] = i; }
            // 选出底牌
            for (int i = 0; i < 53; i++) {
                //选牌范围
                int count = 54 - i;
                // 选牌
                int rIdx = random.nextInt(count);
                // 交换最后一个和选出来的
                int last = idx.length - i - 1;
                idx[last] = idx[last] + idx[rIdx] - (idx[rIdx] = idx[last]);
                pokers.add(getPokerByIdx(idx[last]));
            }
            pokers.add(getPokerByIdx(idx[0]));
        }

        /**
         * 获取底牌和地主牌
         */
        public static String[] getRemainAndSelectLord(Set<String> pork) {
            String[] result = new String[4];
            Random random = new Random();
            int[] idx = new int[54];
            for (int i = 0; i < 54; i++) { idx[i] = i; }
            // 选出底牌
            for (int i = 0; i < 3; i++) {
                //选牌范围
                int count = 54 - i;
                // 选牌
                int rIdx = random.nextInt(count);
                // 交换最后一个和选出来的
                int last = idx.length - i - 1;
                idx[last] = idx[last] + idx[rIdx] - (idx[rIdx] = idx[last]);
                result[i] = getPokerByIdx(idx[last]);
                // 移除底牌
                pork.remove(result[i]);
            }
            // 选出地主牌
            int lordIdx = random.nextInt(51);
            idx[lordIdx] = idx[lordIdx] + idx[51] - (idx[51] = idx[lordIdx]);
            result[3] = getPokerByIdx(idx[51]);
            return result;
        }

        public static void deal(Set<String> pokers, int begin, List<String>... players) {
            int idx = begin;
            for (String poker : pokers) {
                players[idx].add(poker);
                idx = (++idx) % 3;
            }
        }
    }
}
